#include <iostream>
#include <stdio.h>
#include <Python.h>
using namespace std;
namespace python {

/*
运行时，依赖DLL；E:\00c\msys64\usr\bin
INCLUDEPATH += D:/develop/apps/python3/include
LIBS +=E:/00c/msys64/usr/lib/libpython3.11.dll.a
*/
    void getVersion()
    {
        PyObject* pNameObj, * pModule, * pFunc, * pValue;
        char moduleName[] = "3d";
        char func[] = "get_version";

        const char* path[] =
        {
            ".",
            "E:/00workspace/python",
            NULL
        };


        PyObject* sys_path = PySys_GetObject("path");
        for (size_t i = 0; path[i] != NULL; i++)
            PyList_Append(sys_path, PyUnicode_FromString(path[i]));
        
        pNameObj = PyUnicode_FromString(moduleName);
        pModule = PyImport_Import(pNameObj);

        cout<<("导 入 %s  成  功 !", moduleName);


        Py_DECREF(pNameObj);

        if (pModule == NULL)
        {
            cout<<("导 入 %s 失 败 !\n", moduleName);
            return ;
        }
            pFunc = PyObject_GetAttrString(pModule, func);
            if (pFunc && PyCallable_Check(pFunc))
            {
                pValue = PyObject_CallObject(pFunc, NULL);
                if (pValue != NULL) {
                    printf("Python version: %s\n", PyBytes_AS_STRING(pValue));
                    Py_DECREF(pValue);
                }
                else {
                    Py_DECREF(pFunc);
                    Py_DECREF(pModule);
                    PyErr_Print();
                    fprintf(stderr, "Call failed\n");
                }
            }

    }
    void cv2()
    {
        const char* ploylyDemoScript[] =
        {
            "print(sum([1,2,3]))",
            "sum([1,2,3],5)",
            "sum({1,2,3})",
            "sum({1:5,2:6,3:7})",
            "sum(range(1,4))",
            "import  cv2",
            "img = cv2.imread(r'E:\bim\img\bird1.jpg')",
            "cv2.imshow('img',img)",
            "key = cv2.waitKey(0)",
            "cv2.destroyAllWindows()",
            //plotly demo
            "import plotly.graph_objects as go",
            "import numpy as np",
            "N = 1000",
            "t = np.linspace(0, 10, 100)",
            "y = np.sin(t)",
            "fig = go.Figure(data = go.Scatter(x = t, y = y, mode = 'markers'))",
            "fig.show()",
            NULL
        };
        for (size_t i = 0; ploylyDemoScript[i] != NULL; i++)PyRun_SimpleString(ploylyDemoScript[i]);
    }
    int main()
    {
        PyObject* nameObj, * moduleObj, * dic, * func, * args, * rel, * list;

        char* moduleName = const_cast< char*> ("demo");

        const char mysum[] = "mysum";
        const char strsplit[] = "strsplit";

        int i;
        Py_ssize_t listSize;

        printf("\n\n-== 在 C 中 嵌 入 Python==-\n");

        /* Python解释器的初始化*/
        Py_Initialize();

        if (!Py_IsInitialized())
        {
            printf("初始化失败!");
            return -1;
        }

      // getVersion();

        const char* script[] =
        {
            "import  sys",
            "sys.path.append('./')",
            "sys.path.append('E:/00workspace/python')",
            "print(sys.path)",
            "import demo",
             "demo.hello()",
            NULL
        };
        
       
        for (size_t i = 0; script[i]!= NULL; i++)
            PyRun_SimpleString(script[i]);
        //cv2();
        
            //导入模块  
            moduleObj = PyImport_ImportModule(moduleName);

            if (!moduleObj)
            {
                printf("Python get module failed % s ", moduleName);
                return 0;
            }
            printf("导 入 %s  成  功 !", moduleName);
 

        /* 获得模块中函数并检验其有效性 */

        dic = PyModule_GetDict(moduleObj);
        if (!dic)
        {
            printf(" 错 误!");
            return -1;
        }
        const char* funName = "hello";
        func = PyDict_GetItemString(dic, funName);
        if (!PyCallable_Check(func))
        {
            printf("不能找到函数 %s", funName);
            return -1;
        }
        rel = PyObject_CallObject(func, NULL);
        printf("call %s,  result: %s", funName, PyBytes_AS_STRING(PyUnicode_AsEncodedString(rel, "UTF-8", "strict")));

        printf("\n-- --\n");
        /* 获得sum函数地址并验证 */
        func = PyDict_GetItemString(dic, mysum);
        if (!PyCallable_Check(func))
        {
            printf("不能找到函数 %s", mysum);
            return -1;
        }
        /* 构建列表 */
        list = PyList_New(5);
        printf(" 使 用 Python 中 的 sum 函 数 求 解 下 列 数 之 和");
        for (i = 0; i < 5; i++)
            PyList_SetItem(list, i, Py_BuildValue("i", i));

        printf("\n");
        /* 构建sum函数的参数元组*/
        args = PyTuple_New(1);
        PyTuple_SetItem(args, 0, list);
        /* 调用sum函数 */
        rel = PyObject_CallObject(func, args);
       // bodyLogLine("mysum result: %s", PyBytes_AS_STRING(rel));
        if (rel != NULL)
            printf("call %s,  result: %d", mysum, PyLong_AsLong(rel));
        

        /* 获得strsplit函数地址并验证*/
        func = PyDict_GetItemString(dic, strsplit);
        if (!PyCallable_Check(func))
        {
            printf("不能找到函数 %s", strsplit);
            return -1;
        }

        /* 构建strsplit函数的参数元组 */
        args = PyTuple_New(2);
        printf(" 使 用 Python 中 的 函 数 分 割 以 下 字 符 串:\n");
        printf("this is an example\n");

        PyTuple_SetItem(args, 0, Py_BuildValue("s", "this is an example"));
        PyTuple_SetItem(args, 1, Py_BuildValue("s", " "));
        /* 调用strsplit函数并获得返回值 */
        rel = PyObject_CallObject(func, args);
        listSize = PyList_Size(rel);

        printf("结果如下所示:\n");
        for (i = 0; i < listSize; i++)
        {
            auto result=PyList_GetItem(rel, i);
            if (PyBytes_Check(result)) 
                printf("%s\n", PyBytes_AS_STRING(result));
            else if (PyUnicode_Check(result))
            {
                auto rs=PyUnicode_AsEncodedString(result, "UTF-8", "strict");
                printf("%s\n", PyBytes_AS_STRING(rs));
            }
            else
                printf("%s\n", PyBytes_AS_STRING(result));
        }

        /* 释放资源 */
        Py_DECREF(list);
        Py_DECREF(args);
        Py_DECREF(moduleObj);

        /* 结束Python解释器 */
        Py_Finalize();
        printf("结束\n\n");
        return 0;
    }
}
